package com.woniu.config;

import com.woniu.filter.JWTokenFilter;
import com.woniu.handler.*;
import com.woniu.service.SecurityUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableReactiveMethodSecurity;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.server.SecurityWebFilterChain;

import javax.annotation.Resource;

import static com.woniu.constant.Constant.Security.EXCLUDED_PAGES;
import static com.woniu.constant.Constant.Security.SWAGGER_PATH;

@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class SecurityConfig {


    @Resource
    LoginSuccessHandler loginSuccessHandler;

    @Resource
    LoginFailedHandler loginFailedHandler;

    @Autowired
    LogoutSuccessHandler logoutHandler;

    @Autowired
    NoAuthHandler accessDeniedHandler;

    @Autowired
    NoLoginHandler authenticationEntryPoint;

    @Resource
    JWTokenFilter JWTokenFilter;


    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public ReactiveAuthenticationManager reactiveAuthenticationManager(SecurityUserDetailsService userDetailsService) {
        UserDetailsRepositoryReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
        authenticationManager.setPasswordEncoder(passwordEncoder());
        return authenticationManager;
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http, ReactiveAuthenticationManager authenticationManager) {
        return http
                .csrf(ServerHttpSecurity.CsrfSpec::disable)
                .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
                .authenticationManager(authenticationManager)

                .exceptionHandling()
                .accessDeniedHandler(accessDeniedHandler)
                .authenticationEntryPoint(authenticationEntryPoint)

                .and()

                .authorizeExchange()
                .pathMatchers(EXCLUDED_PAGES).permitAll()// 登录放行URL，在common/constant的EXCLUDED_PAGES编辑
                .pathMatchers(HttpMethod.OPTIONS).permitAll()
                .pathMatchers(SWAGGER_PATH).permitAll()
                .pathMatchers("/user-server/test2").hasAuthority("test:test")
                .anyExchange()
                .authenticated()

                .and()

                .formLogin()
                .authenticationSuccessHandler(loginSuccessHandler)
                .authenticationFailureHandler(loginFailedHandler)

                .and()

                .logout()
                .logoutSuccessHandler(logoutHandler)

                .and()

                .addFilterAfter(JWTokenFilter, SecurityWebFiltersOrder.AUTHORIZATION)

                .build();
    }
}
